/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package LogicaNegocio.Validacion;

import LogicaNegocio.Biblioteca.Area;
import LogicaNegocio.Biblioteca.Autor;
import LogicaNegocio.Biblioteca.Editorial;
import LogicaNegocio.Biblioteca.Ejemplar;
import LogicaNegocio.Biblioteca.Libro;
import LogicaNegocio.Biblioteca.Multa;
import LogicaNegocio.Biblioteca.Pedido;
import LogicaNegocio.Biblioteca.Prestamo;
import LogicaNegocio.Biblioteca.Recomendacion;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;


/**
 * Esta clase en java se encarga de validar objetos
 * que componen una biblioteca.
 *
 * @author sebaxtian
 * Archivo: VBiblioteca.java
 * @version 1.0
 * Fecha: jue abr 22 10:15:29 COT 2010
 */


public class VBiblioteca extends Exception {

    //Atributos de clase
    private Object objeto;

    /**
     * Crea un objeto validador de biblioteca
     * sin argumentos que inicializa los atributos a nulo.
     */
    public VBiblioteca() {
        this.objeto = null;
    }

    /**
     * Crea un objeto validador de biblioteca
     * con un argumento que indica el mensaje de
     * excepcion. inicializa a null los atributos.
     *
     * @param mensajeExcepcion
     */
    public VBiblioteca(String mensajeExcepcion) {
        super(mensajeExcepcion);
        this.objeto = null;
    }

    /**
     * Crea un objeto validador de biblioteca que inicializa
     * los atributos a el objeto que recibe como argumento.
     *
     * @param objeto
     * @throws VBiblioteca
     */
    public VBiblioteca(Object objeto) throws VBiblioteca {
        super("Validador de Biblioteca");
        this.objeto = objeto;
        //aqui consulta el tipo de clase al que pertenece el objeto.
        if(objeto.getClass() == Area.class){
            Area objArea = (Area)objeto;
            this.validarCodigo(objArea.getCodigoArea());
            this.validarNombreArea(objArea.getNombre());
            this.validarDescripcionArea(objArea.getDescripcion());
        }
        if(objeto.getClass() == Autor.class){
            Autor objAutor = (Autor)objeto;
            this.validarCodigo(objAutor.getCodigoAutor());
            this.validarPrimerNombre(objAutor.getPrimerNombre());
            this.validarPrimerApellido(objAutor.getPrimerApellido());
            this.validarSegundoNombre(objAutor.getSegundoNombre());
            this.validarSegundoApellido(objAutor.getSegundoApellido());
        }
        if(objeto.getClass() == Editorial.class){
            Editorial objEditorial = (Editorial)objeto;
            this.validarCodigo(objEditorial.getCodigoEditorial());
            this.validarPais(objEditorial.getPais());
            this.validarNombreEditorial(objEditorial.getNombre());
        }
        if(objeto.getClass() == Ejemplar.class){
            Ejemplar objEjemplar = (Ejemplar)objeto;
            this.validarUbicacionEjemplar(objEjemplar.getNumeroSala(), objEjemplar.getNumeroPasillo(), objEjemplar.getNumeroEstante(), objEjemplar.getNumeroCajon());
        }
        if(objeto.getClass() == Libro.class){
            Libro objLibro = (Libro)objeto;
            this.validarISBNLibro(objLibro.getIsbn());
            this.validarTituloLibro(objLibro.getTitulo());
            this.validarAnoPublicacion(objLibro.getAnoPublicacion());
            this.validarIdioma(objLibro.getIdioma());
        }
        if(objeto.getClass() == Multa.class){
            Multa objMulta = (Multa)objeto;
            this.validarMulta(objMulta.getValor());
        }
        if(objeto.getClass() == Pedido.class){
            Pedido objPedido = (Pedido)objeto;
            this.validarCodigo(objPedido.getNumeroPedido());
        }
        if(objeto.getClass() == Prestamo.class){
            Prestamo objPrestamo = (Prestamo)objeto;
            this.validarFechaEntrega(objPrestamo.getFechaEntrega());
        }
        if(objeto.getClass() == Recomendacion.class){
            Recomendacion objRecomendacion = (Recomendacion)objeto;
            this.validarTituloLibro(objRecomendacion.getTitulo());
            this.validarEdicion(objRecomendacion.getEdicion());
            this.validarNombreEditorial(objRecomendacion.getEditorial());
        }
    }

    /**
     * Este metodo valida el formato para el codigo de
     * de un objeto en la biblioteca
     *
     * @param codigo
     * @throws VBiblioteca
     */
    public void validarCodigo(int codigo) throws VBiblioteca {
        String copia = Integer.toString(codigo);
        if(!copia.matches("[1-9][0-9]{3,9}")){
            throw new VBiblioteca("Formato de codigo : "+codigo+" : no valido,\n" +
                    "el codigo debe tener solo caracteres numericos\n" +
                    "con una longitud minima de 4 caracteres y una longitud\n" +
                    "maxima de 9 caracteres");
        }
    }

    /**
     * Este metodo se encarga de validar el nombre para las
     * areas de conocimiento.
     *
     * @param nombre
     * @throws VBiblioteca
     */
    public void validarNombreArea(String nombre) throws VBiblioteca {
        if(nombre == null || !nombre.matches("[a-zñ A-ZÑ]{4,60}")){
            throw new VBiblioteca("Formato de nombre : "+nombre+" : no valido,\n" +
                    "el nombre solo contiene caracteres alfabeticos,\n" +
                    "la longitud minima es de 4 caracteres\n" +
                    "la longitud maxima es de 60 caracteres.");
        }
    }

    /**
     * Este metodo se encarga de validar el formato para la descripcion
     * de un area de conocimieno.
     *
     * @param descripcion
     * @throws VBiblioteca
     */
    public void validarDescripcionArea(String descripcion) throws VBiblioteca {
        if(descripcion == null || !descripcion.matches("[a-zñ A-ZÑ0-9]{8,199}")){
            throw new VBiblioteca("Formato de descripcion : "+descripcion+" : no valido,\n" +
                    "la descripcion solo contiene caracteres alfanumericos,\n" +
                    "la longitud minima es de 8 caracteres y la longitud\n" +
                    "maxima es de 199 caracteres.");
        }
    }

    /**
     * Este metodo valida el primer apellido,
     * la longitud minima permitida es de 3 digitos y la
     * logintud maxima permitida es de 30 digitos.
     * Solo se permiten caracteres alfabeticos entre mayusculas
     * y minusculas.
     *
     * @param primerApellido
     * @throws VBiblioteca
     */
    public void validarPrimerApellido(String primerApellido) throws VBiblioteca {
        if(primerApellido == null || !primerApellido.matches("[a-zñA-ZÑ]{3,30}")){
            throw new VBiblioteca("Formato de primer apellido : "+primerApellido+" : no valido,\n" +
                    "la longitud minima permitida es de 3 digitos,\n" +
                    "logintud maxima permitida es de 30 digitos.\n" +
                    "Solo se permiten caracteres alfabeticos entre mayusculas y minusculas");
        }
    }

    /**
     * Este metodo valida el segundo apellido,
     * la longitud minima permitida es de 3 digitos y la
     * logintud maxima permitida es de 30 digitos.
     * Solo se permiten caracteres alfabeticos entre mayusculas
     * y minusculas.
     *
     * @param segundoApellido
     * @throws VBiblioteca
     */
    public void validarSegundoApellido(String segundoApellido) throws VBiblioteca {
        if(segundoApellido != null){
            if(!segundoApellido.matches("[a-zñA-ZÑ]{3,30}")){
                throw new VBiblioteca("Formato de segundo apellido : "+segundoApellido+" : no valido,\n" +
                        "la longitud minima permitida es de 3 digitos,\n" +
                        "logintud maxima permitida es de 30 digitos.\n" +
                        "Solo se permiten caracteres alfabeticos entre mayusculas y minusculas");
            }
        }
    }

    /**
     * Este metodo valida el primer nombre del,
     * la longitud minima permitida es de 3 digitos y la
     * logintud maxima permitida es de 30 digitos.
     * Solo se permiten caracteres alfabeticos entre mayusculas
     * y minusculas.
     *
     * @param primerNombre
     * @throws VBiblioteca
     */
    public void validarPrimerNombre(String primerNombre) throws VBiblioteca {
        if(primerNombre == null || !primerNombre.matches("[a-zñA-ZÑ]{3,30}")){
            throw new VBiblioteca("Formato de primer nombre : "+primerNombre+" : no valido,\n" +
                    "la longitud minima permitida es de 3 digitos,\n" +
                    "logintud maxima permitida es de 30 digitos.\n" +
                    "Solo se permiten caracteres alfabeticos entre mayusculas y minusculas");
        }
    }

    /**
     * Este metodo valida el segundo nombre del,
     * la longitud minima permitida es de 3 digitos y la
     * logintud maxima permitida es de 30 digitos.
     * Solo se permiten caracteres alfabeticos entre mayusculas
     * y minusculas.
     *
     * @param segundoNombre
     * @throws VBiblioteca
     */
    public void validarSegundoNombre(String segundoNombre) throws VBiblioteca {
        if(segundoNombre != null){
            if(!segundoNombre.matches("[a-zñA-ZÑ]{3,30}")){
                throw new VBiblioteca("Formato de segundo nombre : "+segundoNombre+" : no valido,\n" +
                        "la longitud minima permitida es de 3 digitos,\n" +
                        "logintud maxima permitida es de 30 digitos.\n" +
                        "Solo se permiten caracteres alfabeticos entre mayusculas y minusculas");
            }
        }
    }

    /**
     * Este metodo se encarga de validar el formato para el nombre
     * de un pais.
     * 
     * @param pais
     * @throws VBiblioteca
     */
    public void validarPais(String pais) throws VBiblioteca {
        if(pais == null || !pais.matches("[a-zñ A-ZÑ]{2,29}")){
            throw new VBiblioteca("Formato de pais : "+pais+" : no valido\n" +
                    "El formato para el pais debe contener solo caracteres\n" +
                    "algabeticos de logintud minima de 2 caracteres y longitud\n" +
                    "maxima de 29 caracteres.");
        }
    }

    /**
     * Este metodo se encarga de validar la ubicacion para un ejemplar
     * de la biblioteca.
     * 
     * @param numeroSala
     * @param numeroPasillo
     * @param numeroEstante
     * @param numeroCajon
     * @throws VBiblioteca
     */
    public void validarUbicacionEjemplar(int numeroSala, int numeroPasillo, int numeroEstante, int numeroCajon) throws VBiblioteca {
        String copia1 = Integer.toString(numeroSala);
        String copia2 = Integer.toString(numeroPasillo);
        String copia3 = Integer.toString(numeroEstante);
        String copia4 = Integer.toString(numeroCajon);
        if(!copia1.matches("[1-9][0-9]{0,2}") || !copia2.matches("[1-9][0-9]{0,2}")
                || !copia3.matches("[1-9][0-9]{0,3}") || !copia4.matches("[1-9][0-9]{0,4}")){
            throw new VBiblioteca("Formato ubicacion ejemplar : "+copia1+"-"+copia2+"-"+copia3+"-"+copia4+" : no valido,\n" +
                    "numeroSala debe tener minimo 1 digito maximo 3\n" +
                    "numeroPasillo debe tener minimo 1 digito maximo 3\n" +
                    "numeroEstante debe tener minimo 1 digito maximo 4\n" +
                    "numeroCajon debe tener minimo 1 digito maximo 5");
        }
    }

    /**
     * Este metodo se encarga de validar el formato de ISBN
     * el cual debe cumplir el estandar de diez digitos ó el
     * estandar de trece digitos.
     *
     * @param isbn
     * @throws VBiblioteca
     */
    public void validarISBNLibro(Long isbn) throws VBiblioteca {
        String copia = Long.toString(isbn);
        if(!copia.matches("[1-9][0-9]{9,12}")){
            throw new VBiblioteca("Formato de ISBN : "+isbn+" : no valido,\n" +
                    "el formato de isbn debe cumplir el estandar de diez digitos\n" +
                    "ó el estandar de trece digitos.\n");
        }
    }

    /**
     * Este metodo se encarga de validar el formato
     * para el nombre del titulo del libro.
     *
     * @param titulo
     * @throws VBiblioteca
     */
    public void validarTituloLibro(String titulo) throws VBiblioteca {
        if(titulo == null || !titulo.matches("[a-zñ A-ZÑ]{3,199}")){
            throw new VBiblioteca("Formato de titulo : "+titulo+" : no valido,\n" +
                    "El nombre del titulo debe contener solo caracteres alfabeticos\n" +
                    "la longitud minima es de 8 caracteres y la longitud\n" +
                    "maxima es de 199 caracteres.");
        }
    }

    /**
     * Este metodo se encarga de validar el ano de publicacion
     * para los libros.
     *
     * @param anoPublicacion
     * @throws VBiblioteca
     */
    public void validarAnoPublicacion(Date anoPublicacion) throws VBiblioteca {
        int anoActual = Calendar.getInstance().get(Calendar.YEAR);
        if(anoPublicacion == null){
            throw new VBiblioteca("Debe seleccionar un año de publicacion");
        }
    }

    /**
     * Este metodo se encarga de validar el formato para el idioma.
     * 
     * @param idioma
     * @throws VBiblioteca
     */
    public void validarIdioma(String idioma) throws VBiblioteca {
        if(idioma == null || !idioma.matches("[a-zñ A-ZÑ]{2,20}")){
            throw new VBiblioteca("Formato de idioma : "+idioma+" : no valido,\n" +
                    "El formato de idioma debe tener solo caracteres alfabeticos\n" +
                    "la longitud minima es 2 caracteres y la longitud maxima es 20 caracteres.");
        }
    }

    /**
     * Este metodo se encarga de la validacion del formato
     * de palabras clave sobre algun libro.
     *
     * @param palabrasClave
     * @throws VBiblioteca
     */
    public void validarPalabrasClave(String palabrasClave) throws VBiblioteca {
        if(palabrasClave == null || !palabrasClave.matches("[[a-zñ A-ZÑ]{3,30}[,]]*[a-zñ A-ZÑ]{3,30}")){
            throw new VBiblioteca("Formato de palabras clase : "+palabrasClave+" : no valido,\n" +
                    "las palabras clave debe estar separadas por el caracter [,]\n" +
                    "solo se permiten caracteres alfabeticos.");
        }
    }

    /**
     * Este metodo se encarga de validar el formato para el
     * valor de la multa.
     * 
     * @param multa
     * @throws VBiblioteca
     */
    public void validarMulta(int multa) throws VBiblioteca {
        if(multa < 0){
            throw new VBiblioteca("Formato de multa : "+multa+" : no valido,\n" +
                    "el valor para la multa debe ser un valor entero positivo.");
        }
    }

    /**
     * Este metodo se encarga de validar el formato para
     * la cantidad de pedidos.
     * 
     * @param cantidad
     * @throws VBiblioteca
     */
    public void validarCantidad(int cantidad) throws VBiblioteca {
        if(cantidad <= 0){
            throw new VBiblioteca("Formato de cantidad : "+cantidad+" : no valido,\n" +
                    "el valor para la cantidad debe ser un valor entero positivo\n" +
                    "mayor que cero.");
        }
    }

    /**
     * Este metodo se encarga de la validacio del formato
     * para la edicion.
     * 
     * @param edicion
     * @throws VBiblioteca
     */
    public void validarEdicion(String edicion) throws VBiblioteca {
        if(!edicion.matches("[a-zñ A-ZÑ0-9]{1,19}")){
            throw new VBiblioteca("Formato de edicion : "+edicion+" : no valido,\n" +
                    "formato de edicion debe contener solo caracteres alfabeticos y numericos,\n" +
                    "ejemplo:\n5 Edicion");
        }
    }

    /**
     * Este metodo se encarga de la validacion del formato
     * para el nombre de una editorial.
     * 
     * @param editorial
     * @throws VBiblioteca
     */
    public void validarNombreEditorial(String editorial) throws VBiblioteca {
        if(!editorial.matches("[a-zñ A-ZÑ]{4,29}")){
            throw new VBiblioteca("Formato de editorial : "+editorial+" : no valido,\n" +
                    "formato de editorial debe contener solo caracteres alfabeticos.");
        }
    }

    /**
     * Este metodo se encarga de validar la fecha de entrega para un ejemplar
     * que ha sido prestado de la biblioteca.
     * 
     * @param fecha
     * @throws VBiblioteca
     */
    public void validarFechaEntrega(Date fecha) throws VBiblioteca {
        GregorianCalendar fechaActual = new GregorianCalendar();
        Calendar fechaNueva = Calendar.getInstance();
        fechaNueva.setTime(fecha);
        if(!fechaNueva.after(fechaActual)){
            throw new VBiblioteca("Formato de fecha : "+fechaNueva.get(Calendar.DAY_OF_MONTH)+"/"+fechaNueva.get(Calendar.MONTH)+"/"+fechaNueva.get(Calendar.YEAR)+" : no valido,\n" +
                         "la fecha debe ser una fecha posterior a la fecha actual");
        }
    }
}
